﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DDD.Core;
using MyTestMaterial = DDDTest.Helper.MyTestMaterial;

namespace DDDTest.Core {

    [TestClass]
    public class TestAnimationPlayerRaise {

        AnimationPlayer player;
        int sum1;
        int sum2;

        [TestInitialize()]
        public void ClassInitialize () {
            player = new AnimationPlayer ();
            var obj = new MyTestMaterial ();
        
            var track1 = new AnimationTrack (2, 1, InterpolationType.Linear);
            track1.SetLoopMode (LoopMode.Single);
            track1.SetDuration (100);
            var handler1 = new AnimationEventHandler ((sender, arguments) => {
                sum1 = 1;
            });
            track1.AddEvent (50, handler1, null);

            var clip1 = new AnimationClip ("Clip 1");
            clip1.AddTracker (obj, DDD.Core.Object.GetName (() => obj.R32f), track1);
            player.AddClip (clip1);

            var track2 = new AnimationTrack (2, 1, InterpolationType.Linear);
            track2.SetLoopMode (LoopMode.Single);
            track2.SetDuration (100);
            var handler2 = new AnimationEventHandler ((sender, arguments) => {
                sum2 = 1;
            });
            track2.AddEvent (50, handler2, null);

            var clip2 = new AnimationClip ("Clip 2");
            clip2.AddTracker (obj, DDD.Core.Object.GetName (() => obj.R32f), track2);
            player.AddClip (clip2);
        }

        /// <summary>
        /// アニメーションイベントのRaiseのOnceモードのテスト
        /// </summary>
        [TestMethod]
        public void Test_Raise_Once () {
            // Duration=100, イベントは2つともpos=50
            foreach (var clip in player.Clips) {
                foreach (var track in clip.Tracks) {
                    track.SetLoopMode (LoopMode.Single);
                }
            }

            // 標準的
            var n = player.Raise (0, 99);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;

            // 範囲外
            n = player.Raise (0, 49);
            Assert.AreEqual (0, n);
            n = player.Raise (51, 100);
            Assert.AreEqual (0, n);
            Assert.AreEqual (0, sum1);
            Assert.AreEqual (0, sum2);

            sum1 = sum2 = 0;

            // ピンポイント(start==end)
            n = player.Raise (50, 50);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);
        }

        /// <summary>
        /// アニメーションイベントのRaiseのLoopモードのテスト
        /// </summary>
        [TestMethod]
        public void Test_Raise_Loop () {
            // Duration=100, イベントは2つともpos=50
            foreach (var clip in player.Clips) {
                foreach (var track in clip.Tracks) {
                    track.SetLoopMode (LoopMode.Loop);
                }
            }

            // 標準的
            var n = player.Raise (0, 99);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;

            // 範囲外
            n = player.Raise (0, 49);
            Assert.AreEqual (0, n);
            n = player.Raise (51, 100);
            Assert.AreEqual (0, n);
            Assert.AreEqual (0, sum1);
            Assert.AreEqual (0, sum2);

            sum1 = sum2 = 0;

            // ループした範囲内(+)
            n = player.Raise (100, 199);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;

            // ループした範囲内(-)
            n = player.Raise (-99, 0);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;


            // ピンポイント(start==end)
            n = player.Raise (50, 50);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            // ループしたピンポイント(start==end)
            n = player.Raise (150, 150);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);
        }

        /// <summary>
        /// アニメーションイベントのRaiseのAdditiveLoopモードのテスト
        /// </summary>
        [TestMethod]
        public void Test_Raise_AdditiveLoop () {
            // Duration=100, イベントは2つともpos=50
            foreach (var clip in player.Clips) {
                foreach (var track in clip.Tracks) {
                    track.SetLoopMode (LoopMode.AdditiveLoop);
                }
            }


            // 標準的
            var n = player.Raise (0, 99);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;

            // 範囲外
            n = player.Raise (0, 49);
            Assert.AreEqual (0, n);
            n = player.Raise (51, 100);
            Assert.AreEqual (0, n);
            Assert.AreEqual (0, sum1);
            Assert.AreEqual (0, sum2);

            sum1 = sum2 = 0;

            // ループした範囲内(+)
            n = player.Raise (100, 199);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;

            // ループした範囲内(-)
            n = player.Raise (-99, 0);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            sum1 = sum2 = 0;


            // ピンポイント(start==end)
            n = player.Raise (50, 50);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);

            // ループしたピンポイント(start==end)
            n = player.Raise (150, 150);
            Assert.AreEqual (2, n);
            Assert.AreEqual (1, sum1);
            Assert.AreEqual (1, sum2);
        }
    }
}
